﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PesticideManage.API.Conmon;
using PesticideManage.API.Data;
using PesticideManage.API.Extensions;
using PesticideManage.API.Services.Files;
using PesticideManage.API.Services.Files.Models;
using PesticideManage.Domain.AggregatesModel.BatchQRCodeAggregate;

namespace PesticideManage.API.Controllers;
/// <summary>
/// 一物一码
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class BatchQRCodeController : ControllerBase
{
    private readonly IWebHostEnvironment _env;
    private readonly PesticideContext _context;
    private readonly IStoreService _storeService;

    public BatchQRCodeController(
        IWebHostEnvironment webHostEnvironment,
        PesticideContext context,
        IStoreService storeService
        )
    {
        _env = webHostEnvironment;
        _context = context;
        _storeService = storeService;
    }
    //[HttpGet]
    //public async Task<IActionResult> Get()
    //{
    //    var batchQRCodes =  await _context.BatchQRCodes.OrderByDescending(b=>b.Id).ToListAsync();
    //    return Ok(batchQRCodes);
    //}

    //[HttpGet("{id:int:min(1)}")]
    //public async Task<IActionResult> GetAsync(int id)
    //{
    //    var batchQRCode = await _context.BatchQRCodes.FindAsync(id) ?? throw new InvalidOperationException("二维码不存在");
    //    //Response.Headers.AccessControlExposeHeaders = new Microsoft.Extensions.Primitives.StringValues("Content-Disposition");
    //    //Response.Headers.ContentDisposition = new Microsoft.Extensions.Primitives.StringValues($"attachment; filename={WebUtility.UrlEncode(batchQRCode.FileName)}");
    //    string userName = User.Identity!.Name!;
    //    return _storeService.GetFile(batchQRCode.FileName, userName);
    //}
    [HttpGet("Preview/{id:int:min(1)}")]
    public async Task<string> PreviewAsync(int id)
    {
        var batchQRCode = await _context.BatchQRCodes.Include(c => c.Pesticide).FirstAsync(c => c.Id == id) ?? throw new InvalidOperationException("二维码不存在");

        string traceableId = batchQRCode.CombineTraceableId();
        string value = $"{traceableId}0000001";

        return value;
    }
    [HttpGet("URL/{id:int:min(1)}")]
    [AllowAnonymous]
    public string Get(int id)
    {
        string 前6位 = Utility.ToBase62String((int)DateTimeOffset.Now.ToUnixTimeSeconds());

        string v1 = Utility.ToBase62String(id);
        return $"{前6位}{v1}";
    }
    //[HttpGet("{id:int:min(1)}")]
    [AllowAnonymous]
    [HttpGet("download/{encrypted}")]
    public async Task<IActionResult> GetAsync(string encrypted)
    {
        // 加密字符串前6位为 时间戳
        var timestamp = Utility.FromBase62String(encrypted[..6]);
        var nowTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
        // 确保下载链接只能用一次,重复下载需要登录后点下载获取新的下载链接
        if (nowTimestamp - timestamp > 10)
        {
            return Redirect("/#/NotFound");
            //return NotFound();
        }
        // 前6位为时间戳,后面为id
        var id = Utility.FromBase62String(encrypted[6..]);

        var batchQRCode = await _context.BatchQRCodes.Include(c => c.Pesticide).FirstAsync(c => c.Id == id) ?? throw new InvalidOperationException("二维码不存在");
        // host 根域名
        string? referer = Request.Headers.Referer[0];

        var stream = batchQRCode.ExportTraceableId(referer);
        Response.ContentLength = stream.Length;
        // 设置FileStreamResult的FileDownloadName属性可以修改文件的默认名称。
        // 如果不确定文件格式，可以直接返回MIME值为application/octet-stream。
        // application/octet-stream:响应的内容应该被当作一种文件来处理，而不是直接在浏览器中打开或执行
        return new FileStreamResult(stream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("text/plain")) { FileDownloadName = batchQRCode.FileName };
    }
    [HttpGet]
    public async Task<IActionResult> GetAsync()
    {
        //var host = Request.Host.Value;
        //var webRootPath = _webHostEnvironment.WebRootPath;
        //  int count = _context.BatchQRCodes.Count();
        int userId = User.GetId();
        // 根据用户Id查询二维码
        var res = await _context.BatchQRCodes.Where(q => q.UserId == userId).Select(p => new BatchQRCode
        {
            Id = p.Id,
            CreateTime = p.CreateTime,
            FileName = p.FileName
        }).OrderByDescending(b => b.Id).ToListAsync();
        //var res = _context.BatchQRCodes.OrderByDescending(b => b.Id).ToPageList(pageIndex, pageSize);
        return Ok(res);
    }
    /// <summary>
    /// 创建批量商品二维码
    /// </summary>
    /// <param name="qrcodeDTO">二维码</param>
    /// <body>Sample request:</body>
    /// <returns></returns>
    /// <remarks>
    /// Sample request:
    ///
    ///     POST /Todo
    ///     {
    ///        "PesticideRegistrationType": "第1位农药登记类别代码 1. PD 2. WP 3. 临时登记",
    ///        "LastSixDigitsOfRegistration": ":第2~7位,农药登记证后六位数字",
    ///        "ProductionType": "第8位,生产类型 1. 农药登记证持有人生产 2. 委托加工 3. 委托分装",
    ///        "ProductSpecificationCode": "第9~11位,产品规格码,企业自行编制",
    ///        "GoodsName": "商品描述信息"
    ///     }
    ///
    /// </remarks>
    [HttpPost]
    public async Task<IActionResult> Post(QRCodeDTO qrcodeDTO)
    {
        // 查询产品
        var pesticide = await _context.Pesticides.FindAsync(qrcodeDTO.PesticideId);
        if (pesticide == null)
            return NotFound();

        if (string.IsNullOrEmpty(pesticide.RegistrationNumber) || pesticide.RegistrationNumber.Length < 6)
            return BadRequest();

        //qrcodeDTO.ProductionType = pesticide.ProductionType;
        //qrcodeDTO.LastSixDigitsOfRegistration = pesticide.RegistrationNumber[^6..];
        //qrcodeDTO.PesticideRegistrationType = pesticide.PesticideRegistrationType;
        qrcodeDTO.Host ??= $"{Request.Scheme}://{Request.Host.Value}/#/pesicideinfo/details/";

        //string nowTime = DateTime.Now.ToString("yyMMddHHmm");

        //qrcodeDTO.FileName = $"{pesticide.Name}-{pesticide.NetContent}-{nowTime}.txt";

        // 溯源码 前11位 10952101001000123092204030000001
        ////string strNumer = qrcodeDTO.ToString();
        //string pesticideId = qrcodeDTO.PesticideId.ToString().PadLeft(4, '0');
        //string url = $"{qrcodeDTO.Host}{strNumer}{pesticideId}{nowTime}";
        //int capacity = (url.Length + 9) * qrcodeDTO.Count;
        //StringBuilder stringBuilder = new(capacity);
        //for (int i = 1; i <= qrcodeDTO.Count; i++)
        //{
        //    string oneLine = $"{url}{i.ToString().PadLeft(7, '0')}";
        //    stringBuilder.AppendLine(oneLine);
        //}
        string? userName = User.Identity!.Name;
        if (userName is null)
        {
            return BadRequest("用户未登录");
        }
        //var fileUri = _storeService.CreateFileAsync(qrcodeDTO.FileName, userName, stringBuilder);
        int userId = User.GetId();
        var batchQRCode = new BatchQRCode
        {
            Pesticide = pesticide,
            FileName = $"{pesticide.Name}-{pesticide.NetContent}.txt",
            UserId = userId,
            FileStoreSource = (int)StoreSource.Stream,
            Count = qrcodeDTO.Count
        };
        _context.BatchQRCodes.Add(batchQRCode);
        await _context.SaveChangesAsync();
        return Ok(batchQRCode);
    }

    // DELETE: api/Users/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteBatchQRCode(
        int id,
        [FromServices] LocalStoreService localStoreService,
        [FromServices] TencentCosService tencentCosService
        )
    {
        var batchQRCode = await _context.BatchQRCodes.Include(b => b.Pesticide).FirstOrDefaultAsync(b => b.Id == id);
        if (batchQRCode == null)
            return NotFound();
        var traceableId = batchQRCode.CombineTraceableId();
        InvalidQRCode invalidQRCode = new()
        { TraceableId = traceableId };

        _context.InvalidQRCodes.Add(invalidQRCode);
        batchQRCode.Pesticide = null;
        _context.BatchQRCodes.Remove(batchQRCode);
        await _context.SaveChangesAsync();
        _ = Task.Run(() =>
        {
            string userName = User.Identity!.Name!;
            switch (batchQRCode.FileStoreSource)
            {
                case (int)StoreSource.Local:
                    localStoreService.DeleteFile(batchQRCode.FileName, userName);
                    break;
                case (int)StoreSource.TencentCos:
                    tencentCosService.DeleteFile(batchQRCode.FileName, userName);
                    break;
                default:
                    break;
            }
        });

        return NoContent();
    }
}
